package com.example.lightble;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import com.example.lightble.BLEDeviceManager.onStatusChangedListener;
import com.example.lightble.db.SettingDatabase;
import com.sevencar.activity.HomeFragment;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;


@SuppressLint("NewApi")
public class BlueToothService extends Service implements onStatusChangedListener{

		public static final String ACTION_BLESCAN_FIND_NEWDEVICE ="com.example.bluetooth.le.ACTION_BLESCAN_FIND_DEVICE";  //发现设备.
	  
		private static final String TAG = "sno";
		
		public static String UUID_SERVICE = "00001910-0000-1000-8000-00805f9b34fb";
	    public static String UUID_READ = "0000fff4-0000-1000-8000-00805f9b34fb";
	    public static String UUID_WRITE = "0000fff2-0000-1000-8000-00805f9b34fb";

		private BluetoothAdapter mBluetoothAdapter;
		private BluetoothManager mBluetoothManager;
	    
		private HashMap<String,BLEDeviceManager> mDeviceManagerMap =new  HashMap<String, BLEDeviceManager>();
		private HashMap<String,String> mAutoConnMap=new HashMap<String, String>();
		
		private HashMap<String ,DeviceInfo> mConnectedDevArray=new HashMap<String,DeviceInfo>();
		
		private GattManager mGattManager;
		
		Handler  mTimeHandler;
		Runnable mTimeRunnable;
		
		Handler  mSendSyncCmdHandler;
		Runnable mSendSyncCmdRunnable;
		private final int SEND_SYNCCMD_TIME=30*1000; //30分钟.
		
		public static final int BLEGATT_CONN_TIMEOUT_MESSAGE=601;
		public static final int BLEGATT_CONN_OK_MESSAGE=602;
		public static final int BLEGATT_CONN_CHANGE_MESSAGE=604;  //状态改变了.		
		public static final int BLEGATT_CONN_ERROR_MESSAGE=605;  
		public static final int BLEGATT_CONN_SEND_PASSWD=606;   //需要发送密码.从数据库链表中得到或从界面得到. 
		public static final int BLEGATT_CONN_RCV_DATA=607; 
		public static final int BLEGATT_START_CONN=608; 
		
		
		
	
		private Handler mBleConnectHandler=new Handler(){
			
			@Override
			public void handleMessage(Message msg) {
				BLEDeviceManager devmng=null;
				switch(msg.what) 
				{
						case BLEGATT_CONN_TIMEOUT_MESSAGE:
							devmng=getDeviceItem((BluetoothDevice)msg.obj);
							if(devmng!=null){
								devmng.connectTimeOut();
							}
							break;
						case BLEGATT_CONN_OK_MESSAGE:
							devmng=getDeviceItem((BluetoothDevice)msg.obj);
							if(devmng!=null){
								devmng.setBLEConnected();
							}
							break;
						case BLEGATT_CONN_CHANGE_MESSAGE:
							devmng=getDeviceItem((BluetoothDevice)msg.obj);
							if(devmng!=null){
								devmng.setBLEConnecting(msg.arg1, msg.arg2);
							}
							break;
						case BLEGATT_CONN_ERROR_MESSAGE:
							devmng=getDeviceItem((BluetoothDevice)msg.obj);
							if(devmng!=null){
								devmng.reConnectDevice();
							}
							break;
						case BLEGATT_CONN_SEND_PASSWD:
							devmng=getDeviceItem((BluetoothDevice)msg.obj);
							if(devmng!=null){
								devmng.sendPasswdPkg();
							}
							break;
						case BLEGATT_CONN_RCV_DATA:
							DeviceInfo  rcvInfo=(DeviceInfo)msg.obj;
							devmng=getDeviceItem(rcvInfo.mDevice);
							if(devmng!=null){
								devmng.parseRcvData(rcvInfo.mData);
							}
							break;
						case BLEGATT_START_CONN:
							 String address=(String)msg.obj;
							 if(mBluetoothAdapter!=null)
							 {
								 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
						          if (device == null) {
						              Log.w(TAG, "Device not found.  Unable to connect.");
						          }
						          Log.i(TAG, BlueToothService.class.getSimpleName()+" start connect: "+address);
						          mGattManager.queue(new GattConnectOperation(device)); 
							 }
							break;
						default:
							break;
				}
				super.handleMessage(msg);
			}
		};
		
		private BLEDeviceManager getDeviceItem(BluetoothDevice device)
		{
			return 	mDeviceManagerMap.get(device.getAddress());
		}
		
		@Override
		public void onCreate() 
		{
			super.onCreate();
			HomeFragment.mBLEServiceInstance=this;
			
			initialize();
			
			mSendSyncCmdHandler=new Handler();
			mSendSyncCmdRunnable=new Runnable() {
				
				@Override
				public void run() {
					byte[] tests=CmdSend.getInstance().getSyncBianArray();
					sendData(tests);
					mSendSyncCmdHandler.postDelayed(mSendSyncCmdRunnable, SEND_SYNCCMD_TIME);
				}
			};
			mTimeHandler=new Handler();
			mTimeRunnable=new Runnable() {
				
				@Override
				public void run() {
					if(isScanLoop){
						scanBleDevice();
						mTimeHandler.postDelayed(this,1000); //30*60*1000  三十分钟发一次.
					}
				}
			};
			
			SettingDatabase  sdb = new SettingDatabase(this, 0);
			mAutoConnMap= sdb.getDevicePasswdLists();
			sdb.close();
			Log.i("sno","mAutoConnMap size is:"+mAutoConnMap.size());
			Set<String> strlist=mAutoConnMap.keySet();
			for (String str : strlist) {
				Log.i("sno","mAutoConnMap==="+str);
			}
			
			mSendSyncCmdHandler.postDelayed(mSendSyncCmdRunnable, SEND_SYNCCMD_TIME);
			
			
			setScanLoop(true);
    		startScanBle(); 
			
		}
		@SuppressLint("NewApi")
		@Override
		public void onDestroy() {
			super.onDestroy();
			 if(mBluetoothAdapter!=null){
				  mBluetoothAdapter.stopLeScan(mLeScanCallback);
			 }
				Set<String> setString=mDeviceManagerMap.keySet();
				for (String address : setString) {
					BLEDeviceManager devmng=mDeviceManagerMap.get(address);
					devmng.onDestoryDev();
				}
				mDeviceManagerMap.clear();
				mConnectedDevArray.clear();
				
				mBluetoothAdapter = null;	
				mTimeHandler.removeCallbacks(mTimeRunnable);
				mSendSyncCmdHandler.removeCallbacks(mSendSyncCmdRunnable);
				Log.i("sno","BlueToothService::onDestroy----------- ");
		}
		@SuppressLint("NewApi")
		private boolean initialize() {
				if (mBluetoothManager == null) 
				{
		            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
		            if (mBluetoothManager == null) {
		                Log.e("sno", "Unable to initialize BluetoothManager.");
		                return false;
		            }
		        }
		        mBluetoothAdapter = mBluetoothManager.getAdapter();
		        if (mBluetoothAdapter == null) {
		            Log.e("sno","Unable to obtain a BluetoothAdapter.");
		            return false;
		        }
		        mGattManager=new GattManager(getApplicationContext(),mBleConnectHandler);
		        return true;
	    }
		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			Log.i("sno","Service::onStartCommand.....");
			return START_STICKY;
		}
	
		    private boolean isScanLoop=true;
		    public void setScanLoop(boolean isLoop)
		    {
		    	isScanLoop=isLoop;
		    }
			public synchronized void startScanBle()
			{
				mTimeHandler.post(mTimeRunnable);
			}
			@SuppressLint("NewApi")
			private synchronized void scanBleDevice()
			{
			//	Log.i("sno","startScanBle.....");
				if(mBluetoothAdapter==null)
				{
					mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
				}
				if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) 
				{
					mBluetoothAdapter.stopLeScan(mLeScanCallback);
					new Handler().postDelayed(new Runnable() {
						
						@SuppressLint("NewApi")
						@Override
						public void run() {
							if(mBluetoothAdapter!=null){
								boolean bb = 	mBluetoothAdapter.startLeScan(mLeScanCallback);
								System.out.println("bb is " + bb);
							}
							
							
							
						}
					}, 100);
				}
			}
			@SuppressLint("NewApi")
			public synchronized void stopScanBle()
			{
				isScanLoop=false;
				if(mBluetoothAdapter!=null)
					mBluetoothAdapter.stopLeScan(mLeScanCallback);
			}
			public boolean isShowing;
			private BluetoothAdapter.LeScanCallback mLeScanCallback=new BluetoothAdapter.LeScanCallback() 
			{
			        @Override
			        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) 
			        { 
			        	
			        	System.out.println("device scaned --- " + device.getAddress());
			        	if (device != null )
			        	{
			        		byte apptype=(byte)CmdConstants.CMD_APP_BYTE;
							byte apptype2=(byte)(~apptype);
							
			        		if(scanRecord.length>20 && scanRecord[5]==apptype && scanRecord[6]==apptype2)  //只接收当前设备.
			        		{
								BLEDeviceManager  devmng;
								if(mDeviceManagerMap.containsKey(device.getAddress())==false){
						        	devmng=new BLEDeviceManager(BlueToothService.this, device);
						        	mDeviceManagerMap.put(device.getAddress(), devmng);
						        }else {
						        	devmng=mDeviceManagerMap.get(device.getAddress());
						        }
								
								if(mAutoConnMap.containsKey(device.getAddress()))  //能扫描到,就去连接.
				        			devmng.startConnectAuto();
								
							        final Intent intent = new Intent(ACTION_BLESCAN_FIND_NEWDEVICE);
							        intent.putExtra("BluetoothDevice",device);
							        sendBroadcast(intent);
							 }
						}
			        }
			 };
			 public  HashMap<String ,DeviceInfo> getConectedDevices()
			 {
				 return mConnectedDevArray;
			 }
			 public ArrayList<BluetoothDevice> getScanedDeviceArray()
			 {
				 ArrayList<BluetoothDevice> devicelist=new ArrayList<BluetoothDevice>();
				 Set<String> addresslist=mDeviceManagerMap.keySet();
				 for (String addres : addresslist) {
					 BLEDeviceManager item=mDeviceManagerMap.get(addres);
					devicelist.add(item.getDevice());
				}
				 return devicelist;
			 }
			 public String getPasswdFromDatabase(String address)
			 {
				 return mAutoConnMap.get(address);
			 }
			 public void saveBondPasswdToDatabase(String address,String passwd)
			 {
				 if(mAutoConnMap.containsKey(address)){
//					 SettingDatabase.getInstance().updateDevicePasswd(address, passwd);
					 SettingDatabase sdb = new SettingDatabase(this,1);
					 sdb.updateDevicePasswd(address, passwd);
					 sdb.close();
				 }else{
//					 SettingDatabase.getInstance().addDevicePasswd(address, passwd);
					 SettingDatabase sdb = new SettingDatabase(this,1);
					 sdb.addDevicePasswd(address, passwd);
					 sdb.close();
				 }
				 mAutoConnMap.put(address, passwd);
			 }
			 
			 public void startConnectByUser(String address)
			 {
				 BLEDeviceManager item=mDeviceManagerMap.get(address);
				 if(item!=null){
					 item.startConnectByUser();
				 }
			 }
			 public void setDisconnectByUser(String address)
			 {
				 BLEDeviceManager item=mDeviceManagerMap.get(address);
				 if(item!=null){
					 item.setDisconnect(true,true);
				 }
			 }
			 public void sendNewPasswdByUser(String address, String passwd)
			 {
				 BLEDeviceManager item=mDeviceManagerMap.get(address);
				 if(item!=null){
					 item.sendNewPasswdPkg(passwd);
					 System.out.println("--pwd");
				 }else{
					 System.out.println("--pwd---5");
				 }
			 }
//-------------------------------------------mGatt-----------------------------------------------------		
	 /**
	  * @param bytes
	  * @param gatt
	  */
	    public synchronized void sendDataToAddress(byte[] bytes,String address)
	    {
	         if(address!=null){
	        	 mGattManager.sendDataToAddress(bytes, address);
	         }else{
	        	 Log.w(TAG, "sendDataToAddress address==null");
	         }
	    }
	    /**
	     * 
	     * @param bytes
	     * @param grouplist
	     */
	    public synchronized void sendData(byte[]  bytes,ArrayList<String> grouplist)
	    {
	    	for(int i=0;i<grouplist.size();i++)
	    	{
	    		String address=grouplist.get(i);
	    		Set<String> keys=mConnectedDevArray.keySet();
	    		if(keys.contains(address)){
	    			mGattManager.sendDataToAddress(bytes,address);
		    	}
	    	}
	    }
	    /**
	     * 在这里增加群组的设备.
	     * @param bytes
	     */
	    public synchronized void sendData(byte[]  bytes)
	    {
	    	if(mConnectedDevArray.isEmpty()){
	    		Log.e("sno","BLEService sendData error mConnectedGattArray is empty");	
	    		return ;
	    	}
	    	Log.i("sno","mConnectedGattArray count is:"+mConnectedDevArray.size());
	    	
	    	Set<String> keys=mConnectedDevArray.keySet();
	    	for (String address :keys) 
	    	{
	    		mGattManager.sendDataToAddress(bytes,address);
	    	}
	    }
	    public synchronized void disconnectBle(BluetoothDevice device) 
	    {
	        if (mBluetoothAdapter == null || device == null) 
	        {
	            Log.w(TAG, "disconnectBle error:null");
	            return;
	        }
	        Log.i(TAG, "BlueToothService::disconnectBle: "+device.getName());
    	   if(mConnectedDevArray.containsKey(device.getAddress()))
    	   {
    		   mConnectedDevArray.remove(device);  
    	   }
		   mGattManager.disConnectBle(device.getAddress());
	    }
	    /**
	     * 开始连接...>>>  
	     * @param address
	     * @param isSendPasswd
	     * @return
	     */
	    public synchronized boolean connectBle(String address)
	  	{
	          Message msg1=mBleConnectHandler.obtainMessage(BLEGATT_START_CONN);
	          msg1.obj=address;
	          mBleConnectHandler.sendMessage(msg1);
	  		  return true;
	  	}
	    /**
	     * 连接好后, 增加到设备中.
	     */
	    public synchronized void addToConnectGattArray(BluetoothDevice device,boolean isOpen)
	    {
	    	if(mConnectedDevArray.containsKey(device.getAddress())==false)
	    	{
	    		mConnectedDevArray.put(device.getAddress(),new DeviceInfo(device,isOpen));
	    		Log.i("sno","addToConnectGattArray -device: "+device.getName());
	    	}else{
	    	}
	    	
	    	byte[] tests=CmdSend.getInstance().getSyncBianArray();
			sendData(tests);
	    }
	    /**
	     * 断开后,从array中去掉.
	     * @param gatt
	     * @return
	     */
	    public synchronized boolean removeFromConnectGattArray(BluetoothDevice device)
	    {
	    	if(mConnectedDevArray.containsKey(device.getAddress()))
	    	{
	    		mConnectedDevArray.remove(device);
	    		Log.i("sno","removeFromConnectGattArray -device: "+device.getName());
	    		return true;
	    	}else{
	    		return false;
	    	}
	    }
		public class LocalBinder extends Binder {

			BlueToothService getService() {
				return BlueToothService.this;
			}
		}

		// This is the object that receives interactions from clients. See
		private final IBinder mBinder = new LocalBinder();

		@Override
		public IBinder onBind(Intent intent) {
			return mBinder;
		}
		
		 private void printRcvData(String hint,byte[] data)
			{
				String printStr="";
				printStr+=" >>> ";
		    	printStr+=Integer.toString(data.length);
		    	printStr+="hex:";
		    	
				for(int i=0;i<data.length;i++)
				{
					 int v = data[i] & 0xFF;
					 printStr+= Integer.toHexString(v);
					 printStr+=" ";
				}
				Log.i("sno",hint+printStr);
			}

		 @Override
		public void onStatusChanged(BLEDeviceManager devmng, int status)  //状态 -1:一致连不上, -2:设备断开后扫描不到.这里都清除.
		 {
		// TODO Auto-generated method stub
			 String address=devmng.getDevice().getAddress();
				if(mDeviceManagerMap.containsKey(address))
				{
					devmng.onDestoryDev();
					mDeviceManagerMap.remove(address);
				}
		}
		 //service可以用Toast来显示.
		 public void showToast()
		 {
			// Toast.makeText(BlueToothService.this, "showToast",Toast.LENGTH_SHORT).show();
		 }
}
